package com.zxy.ziems.server.statistics.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.zxy.ziems.server.classify.pojo.entity.Classify;
import com.zxy.ziems.server.classify.pojo.entity.ClassifyDeviceProperty;
import com.zxy.ziems.server.classify.service.ClassifyService;
import com.zxy.ziems.server.constant.enums.CalculateTypeEnum;
import com.zxy.ziems.server.device.mapper.DeviceMapper;
import com.zxy.ziems.server.domain.cim.EmsEceDayData;
import com.zxy.ziems.server.dto.zieceuse.*;
import com.zxy.ziems.server.energy.mapper.DataTempMapper;
import com.zxy.ziems.server.energy.mapper.DeviceMeasureDataDayMapper;
import com.zxy.ziems.server.energy.pojo.dto.DeviceMeasureDateDTO;
import com.zxy.ziems.server.energy.service.DataChartService;
import com.zxy.ziems.server.energy.service.DeviceTypeDataService;
import com.zxy.ziems.server.energy.service.EnergyPriceService;
import com.zxy.ziems.server.mapper.EmsEceDayDataMapper;
import com.zxy.ziems.server.statistics.service.ZieceDataService;
import com.zxy.ziems.server.utils.DateUtils;
import com.zxy.ziems.server.vo.ChartVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.zxy.ziems.server.utils.DateUtils.YMD_PATTERN;

@Slf4j
@Service
public class ZieceDataServiceImpl implements ZieceDataService {

    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceMeasureDataDayMapper deviceMeasureDataDayMapper;
    @Autowired
    private ClassifyService classifyService;
    @Autowired
    private DataChartService dataChartService;
    @Autowired
    private DeviceTypeDataService deviceTypeDataService;
    @Autowired
    private EmsEceDayDataMapper emsEceDayDataMapper;
    @Autowired
    private EnergyPriceService energyPriceService;

    // 数据类型
    private static final String ELECTRICITY_DATA_TYPE_ID = "1770381347331145728";

    @Override
    public List<Object> getAllData(String dataClassify, LocalDate date) {
        return List.of();
    }

    @Override
    public BasicData getBasicData(String dataClassify, LocalDate date) {
        return null;
    }

    @Override
    @Transactional
    public ElectricityData getElectricityData(String dataClassify, LocalDate date) {
        log.info("=====开始计算"+date+"号的电力数据=====");
        // 获取表，后续如果表下大类新增，在该代码基础上进行更改即可
        List<Classify> tableClassifyList = classifyService.getChildrenClassify(dataClassify);
        // 获取表下大分类,key为表id,value为大分类
        Map<String,List<Classify>> classifyMap = new HashMap<>();
        tableClassifyList.forEach(table -> {
            List<Classify> classifys = classifyService.getChildrenClassify(table.getClassifyId());
            classifyMap.put(table.getClassifyName(),classifys);
        });
        // 获取分类下对应数据字段,以及数据字段下子项的值
        Map<String,List<Classify>> dataFieldMap = new HashMap<>();
        classifyMap.forEach((tableId,classifys) -> {
            classifys.forEach(classify -> {
                List<Classify> dataFields = classifyService.getChildrenClassify(classify.getClassifyId());
                dataFieldMap.put(classify.getClassifyName(),dataFields);
            });
        });

        // 数据类型使用增量计算
        int calculateType = 2;
        String queryType = "custom";
        String queryDate = date.toString();
        ElectricityData electricityData = new ElectricityData();
        dataFieldMap.forEach((classifyId,dataFields) -> {
            dataFields.forEach(dataField -> {
                try {
                    DeviceMeasureDateDTO measureDateDTO = getClassifyDeviceData(queryType,queryDate,calculateType,dataField);
                    if(ObjectUtils.isNotEmpty(measureDateDTO)){
                        // 存储点位数值合计
                        if(electricityData.getClass().getDeclaredField(dataField.getDescription()).getName().equals(dataField.getDescription())){
                            setFieldValue(electricityData,dataField.getDescription(),measureDateDTO.getStatistic());
                        }
                    }else{
                        // 存储点位数值合计
                        if(electricityData.getClass().getDeclaredField(dataField.getDescription()).getName().equals(dataField.getDescription())){
                            setFieldValue(electricityData,dataField.getDescription(),0.00);
                        }
                    }

                } catch (NoSuchFieldException e) {
                    throw new RuntimeException(e);
                }
            });
        }
        );

        // 处理总用电量powerConsumption
        DeviceMeasureDateDTO measureDateDTO = getClassifyDeviceData(queryType,queryDate,calculateType,tableClassifyList.get(0));
        if(!ObjectUtils.isEmpty(measureDateDTO)){
            setFieldValue(electricityData,"powerConsumption",measureDateDTO.getStatistic());
        }
        // 处理FAC单价
        // 将 LocalDate 类型的日期转换为 LocalDateTime 类型，时间设置为当天的 10 点
        LocalDateTime localDateTime = date.atTime(10, 0);
        BigDecimal price = energyPriceService.getEnergyPriceByDataTypeId(ELECTRICITY_DATA_TYPE_ID, localDateTime);
        if (price.compareTo(BigDecimal.ZERO)>0){
            setFieldValue(electricityData,"facUnivalent",price);
        }
        // 存储到厂务能管对接表中
        List<EmsEceDayData> emsEceDayDataList = new ArrayList<>();
        Class<?> electricityDataClass = ElectricityData.class;
        Field[] fields = electricityDataClass.getDeclaredFields();
        int fieldCount = fields.length;
        for (int i = 0; i < fieldCount; i++) {
            EmsEceDayData emsEceDayData = new EmsEceDayData();
            emsEceDayData.setDataTime(date);
            emsEceDayData.setDataClassify("电");
            emsEceDayData.setDataTable(tableClassifyList.get(0).getClassifyName());
            emsEceDayData.setDataName(fields[i].getName());
            emsEceDayData.setDataValue(getFieldValue(fields[i],electricityData));
            emsEceDayDataList.add(emsEceDayData);
        }
        emsEceDayDataMapper.batchAdd(emsEceDayDataList);
        log.info("====="+date+"号的电力数据计算完成=====");
        return null;
    }

    @Override
    public WaterData getWaterData(String dataClassify, LocalDate date) {
        return null;
    }

    @Override
    public GasData getGasData(String dataClassify, LocalDate date) {
        return null;
    }

    @Override
    public AcData getAcData(String dataClassify, LocalDate date) {
        return null;
    }

    @Override
    public AcData getProcessData(String dataClassify, LocalDate date) {
        return null;
    }

    // 获取该分类下的设备数据
    public DeviceMeasureDateDTO getClassifyDeviceData(String queryType,String queryDate,int calculateType,Classify classify){
        List<ClassifyDeviceProperty> devicePropertyList = dataChartService.getClassifyDeviceProperties(classify.getClassifyId());
        if(!devicePropertyList.isEmpty()){
            Set<String> deviceIdSet = devicePropertyList.stream().map(ClassifyDeviceProperty::getDeviceId).collect(Collectors.toSet());
            ClassifyDeviceProperty classifyDeviceProperty = devicePropertyList.get(0);
            // 设备参数ID
            String dataTypeId = classifyDeviceProperty.getDataTypeId();
            // 查询该分类下设备数据的和
            List<DeviceMeasureDateDTO> dateDtos = getDeviceMeasureDateTypeDtos(queryType,queryDate,queryDate,classify,deviceIdSet,dataTypeId,calculateType);
            return dateDtos.get(0);
        }
        return null;
    }

    // 获取类型中的数据值
    public BigDecimal getFieldValue(Field field,ElectricityData electricityData){
        try {
            // 获取字段的访问权限
            field.setAccessible(true);
            // 获取字段的值
            Object value = field.get(electricityData);
            BigDecimal bigDecimalValue;
            if (value instanceof Integer) {
                bigDecimalValue = java.math.BigDecimal.valueOf((Integer) value);
            } else if (value instanceof Double) {
                bigDecimalValue = java.math.BigDecimal.valueOf((Double) value);
            } else if (value instanceof java.math.BigDecimal) {
                bigDecimalValue = (java.math.BigDecimal) value;
            } else {
                // 处理其他类型，例如可以设置为 null 或者抛出异常
                bigDecimalValue = null;
            }
            // 给 EmsEceDayData 的 DataValue 字段赋值
            return bigDecimalValue;
        }catch (IllegalAccessException e){
            throw new RuntimeException(e);
        }

    }

    public void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            // 获取对象的类
            Class<?> clazz = obj.getClass();
            // 获取指定名称的字段
            Field field = clazz.getDeclaredField(fieldName);
            // 设置可访问，即使字段是 private 也能访问和修改
            field.setAccessible(true);
            // 给字段赋值
            BigDecimal bigDecimalValue;
            if (value instanceof Integer) {
                bigDecimalValue = java.math.BigDecimal.valueOf((Integer) value);
            } else if (value instanceof Double) {
                bigDecimalValue = java.math.BigDecimal.valueOf((Double) value);
            } else if (value instanceof java.math.BigDecimal) {
                bigDecimalValue = (java.math.BigDecimal) value;
            } else {
                // 处理其他类型，例如可以设置为 null 或者抛出异常
                bigDecimalValue = null;
            }
            field.set(obj, bigDecimalValue);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 前提条件（所有设备dataTypeId是一致的）
     *
     * @param queryType
     * @param startDay
     * @param endDay
     * @param classify
     * @param deviceIdSet
     * @param dataTypeId
     * @return
     */
    private List<DeviceMeasureDateDTO> getDeviceMeasureDateTypeDtos(String queryType, String startDay, String endDay, Classify classify, Set<String> deviceIdSet, String dataTypeId, Integer calculateType) {
        List<DeviceMeasureDateDTO> dateDtos = new ArrayList<>();

        if (calculateType.equals(CalculateTypeEnum.MEASURE.getCode())) {
            // 如果是实时值，获取平均的统计
            dateDtos = deviceTypeDataService.avgTree(classify.getClassifyId(), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                    DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
        } else if (calculateType.equals(CalculateTypeEnum.INCREMENT.getCode())) {
            // 如果是增量值，获取求和统计
            dateDtos = deviceTypeDataService.sumTree(classify.getClassifyId(), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                    DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
        } else if (calculateType.equals(CalculateTypeEnum.MEASURE_INCREMENT.getCode())) {
            // 如果是实时增量值（采集值是按小时统计的值），天统计则会使用实际值求和
            dateDtos = deviceTypeDataService.sumTreeReal(classify.getClassifyId(), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                    DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
        }

        return dateDtos;
    }



}
